var db = require("../utils/db");
var logger = require("../utils/log");

var roomMgr = require("./roommgr");
var socketMgr = require("./socket_service");
var userMgr = require("./usermgr");

var games = {};
var gameSeatsOfUsers = {};

var isTiming = false;
var interval = null;

const PERIOD_READY_0 = 4; //准备
const PERIOD_HOLD_1 = 4; //手牌
const PERIOD_ZHUANG_2 = 14; //通知庄one
const PERIOD_HOLD_MORE_3 = 24; //补牌
const PERIOD_ZHU_4 = 24; //通知注all
const PERIOD_OPEN_5 = 34; //开牌
const PERIOD_PAI_6 = 44; //积分
const PERIOD_SCORE_7 = 44; //积分
const PERIOD_END_8 = 48; //结束

//开始牌局 房主才可以
function begin(roomId) {
    var room = roomMgr.getRoomByRoomID(roomId);
    logger.error("begin", roomId);
    if(room == null) return;
    setupData(room);

    if (isTiming) return;
    isTiming = true;
    beginTimer();
}

function beginTimer() {
    interval = setInterval(function () {
        if (games.length < 1) {
            clearInterval(interval);
            isTiming = false;
            interval = null;
        }

        for (var roomId in games) {
            var game = games[roomId];
            if (game == null) continue;

            if (game.timeCount == PERIOD_HOLD_1) { //发手牌 通知抢庄
                xiPai(game);
                faPai(game);

                socketMgr.notify_holds(game);
                game.state = PERIOD_HOLD_1;
            } else if (game.timeCount == PERIOD_ZHUANG_2) { //通知庄家
                calcZhuang(game);

                socketMgr.notify_zhuang_result(game);
                game.state = 14;
            } else if (game.timeCount == PERIOD_HOLD_MORE_3) { //补手牌
                calcZhu(game);

                socketMgr.notify_holds_more(game);
                game.state = 24;
            } else if (game.timeCount == PERIOD_ZHU_4) { //通知注
                buPai(game);

                socketMgr.notify_zhu_remain(game);
                game.state = 24;
            } else if (game.timeCount == PERIOD_OPEN_5) { //通知开牌

                socketMgr.notify_open(game);
                game.state = 34;
            } else if (game.timeCount == PERIOD_PAI_6) { //通知牌型
                biPai(game);

                socketMgr.notify_pai(game);
                game.state = 34;
            } else if (game.timeCount == PERIOD_SCORE_7) {//通知积分
                calcScore();

                socketMgr.notify_score(game);
                game.state = 44;
            } else if (game.timeCount == PERIOD_END_8) {//44s-48s 通知本局游戏完成 第48s游戏结束

                socketMgr.notify_game_end(game);
                game.state = 48;

                game.room.numOfGames++;
                readyNextGame(game);
                game.state = 0;
            }
        }
    }, 2000);
};

//结束牌局
function end(roomId) {
    delete games[roomId];

    if (games.length < 1) {
        clearInterval(interval);//停止定时器
        isTiming = false;
    }
};

//初始化数据
function setupData(room) {

    //牌局共享的数据 包括状态 顺序 出牌
    var game = {
        room:room,
        type:0, //1是牛牛 2是扎金花 3是斗地主 4是麻将
        timeCount:0, //用于定时器计数

        //游戏52张牌
        pkPais:null,
        //座位信息
        gameSeats:new Array(6),
        //0 准备下一局  999正在请求解散
        state:-1,

        //抢庄
        memberOfZhuang:0,
        //下注
        memberOfZhu:0,
        //亮牌
        memberOfOpen:0,
        //庄
        zhuang:null,
        //庄倍数 最小一倍
        zhuangBei:-1,
    };

    var ps = room.players.length;
    for (var i = 0; i < ps; i++) {
        var seat = game.gameSeats[i] = {};

        seat.game = game;
        seat.seatIndex = i;
        seat.userId = room.players[i].userId;

        //持有的牌
        seat.holds = [];
        //补牌
        seat.holdsMore = -1;

        //抢庄 0代表不抢 2，4代表抢购的倍数
        seat.zhuang = -1;
        //筹码
        seat.zhu = -1;
        //牛几 亮牌
        seat.niuX = -1;
        //得分信息
        seat.score = -1;

        gameSeatsOfUsers[seat.userId] = seat;
    }

    room.numOfGames = 1;

    games[room.roomId] = game;

    return game;
}

function readyNextGame(game) {

   if (game.room.numOfGames > 1) {
        //记录结果
        db.set_game_result(game.room.uuid, game.room.numOfGames, game.pWin, game.zhuInfo, null);

        if (game.room.numOfGames == 20) { //20局 游戏结束
            var ps = game.gameSeats.length;
            for (var i = 0; i < ps; i++) {
                var seat = game.gameSeats[i];
                delete gameSeatsOfUsers[seat.userId];
            }
            delete games[game.room.roomId];

            userMgr.kickAllInRoom(game.room.roomId);

            roomMgr.closeRoom(game.room.roomId);
        } else {
            game.memberOfZhuang = 0;
            game.memberOfZhu = 0;
            game.memberOfOpen = 0;

            game.zhuang = null;
            game.zhuangZhu = -1;

            var ps = game.gameSeats.length;
            for (var i = 0; i < ps; i++) {
                var seat = game.gameSeats[i];
                seat.holds = [];
                seat.holdsMore = -1;
                seat.zhuang = -1;
                seat.zhu = -1;
                seat.niuX = -1;
                seat.score = -1;
            }
        }
    }
}

//洗牌
function xiPai(game) {
    //如果牌够 就不用洗牌
    if (game.pkPais.length >= game.type)

    var pkPais = new Array(52);

    //40-52黑桃 27-39红桃 14-26梅花 1-13方块
    var index = 0;
    for (var i = 1; i < 53; i++) {
        pkPais[index] = i;
        index++;
    }

    //乱序
    for (var i = 0; i < 52; i++) {
        var lastIndex = 51-i;
        var index = Math.floor(Math.random() * lastIndex);
        var t = pkPais[index];
        pkPais[index] = pkPais[lastIndex];
        pkPais[lastIndex] = t;
    }
}

//发牌
function faPai(game) {
    var seatIndex = 0;

    //todo 长度不固定
    var room = game.room;
    var paiLength = 0;

    var bupai = false;
    var ps = room.players.length;
    if (room.type == 12) {
        paiLength = 4*ps;
        bupai = true;
    }

    var i  = 0;
    for (; i < paiLength; i++) {
        seatIndex = seatIndex%ps;

        var seat = game.gameSeats[seatIndex];
        var pai = pkPais[i];
        seat.holds.push(pai);

        seatIndex ++;
    }

    if (bupai) { //补牌阶段
        for (; i < ps; i++) {
            seatIndex = seatIndex%ps;

            var seat = game.gameSeats[seatIndex];
            var pai = pkPais[i];
            seat.holdsMore = pai;

            seatIndex ++;
        }
    }
};

function calcZhuang(game) {
    var seats = game.gameSeats;
    var ps = seats.length;

    //有人没抢庄设置成抢庄0倍
    for (var i = 0; i < ps; i++) {
        var seat = seats[i];
        if (seat.zhuang < 0) {
            seat.zhuang = 0;
        }
    }
    //没人抢庄
    if (game.zhuangBei < 0) {
        game.zhuangBei = 0;
    }

    var zhuangs = [];
    for (var i = 0; i < ps; i++) {
        var seat = seats[i];
        if (seat.zhuang >= game.zhuangBei) {
            zhuangs.push(seat.userId);
        }
    }
    //没人抢庄
    if (game.zhuangBei == 0) {
        game.zhuangBei = 1;
    }

    var index = randomIndex(zhuangs.length);
    game.zhuang = zhuangs[index];
};

function biPai(game) {
    var seats = game.gameSeats;
    var ps = seats.length;

    //有人没亮牌
    for (var i = 0; i < ps; i++) {
        var seat = seats[i];
        if (seat.niuX < 0) {

            seat.holds = seat.holds.sort(function (a, b) {
                return b - a; //从大到小
            });
            seat.niuX = suanNiu(seat.holds);
        }
    }
}

function calcScore(game) {
    var seats = game.gameSeats;
    var ps = seats.length;

    seats = seats.sort(function (sa, sb) {
        if (sb.niuX == sa.niuX) { //牛同样的牛
            return sb[0] - sa[0];//从大到小
        } else {
            return sb.niuX - sa.niuX;//从大到小
        }
    });

    var isPlus = true;
    var zhuangScore = 0;

    var zhuangWinScore = 0;
    var zhuangIndex = -1;

    var gameScore = [];

    for (var i = 0; i < ps; i++) {
        var seat = seats[i];
        if (seat.userId === game.zhuang) {
            isPlus = false;
            zhuangWinScore = suanBeishu(seats.niuX)*game.zhuangBei;
            zhuangIndex = i;
            continue;
        }
        if (isPlus) {
            var winScore = suanBeishu(seat.niuX)*game.zhuangBei; //闲家的倍数
            zhuangScore -= winScore;
            var info = {
                userId: seat.userId,
                score: winScore,
            };
            gameScore.push(info);
        } else {
            var shuScore = zhuangWinScore;
            zhuangScore += shuScore;
            var info = {
                userId: seat.userId,
                score: shuScore,
            };
            gameScore.push(info);
        }
    }
    var info = {
        userId: game.zhuang,
        score: zhuangScore,
    };
    gameScore.splice(zhuangIndex, 0 , info);
    game.room.results.push(gameScore);
};

//下注
function xiaZhu(userId,zhu) {
    var seat = gameSeatsOfUsers[userId];
    if(seat == null){
        log.warn("can't find user game data.");
        return;
    }

    if (seat.zhu < 0) {
        seat.memberOfZhu++;
        seat.zhu = zhu;
    }

    //如果所有人都下注完成
    var game = seat.game;
    if (game.timeCount < PERIOD_ZHU_END_3 && seat.memberOfZhu == game.gameSeats.length) {
        game.timeCount =  PERIOD_ZHU_END_3;
    }
};

//开牌
function kaiPai(userId) {
    var seat = gameSeatsOfUsers[userId];
    if(seat == null){
        log.warn("can't find user game data.");
        return;
    }

    if (seat.niuX < 0) {
        seat.memberOfOpen++;

        seat.holds = seat.holds.sort(function (a, b) {
            return b - a; //从大到小
        });
        seat.niuX = suanNiu(seat.holds);
    }

    //如果所有人都下注完成
    var game = seat.game;
    if (game.timeCount < PERIOD_OPEN_END_4 && seat.memberOfZhu == game.gameSeats.length) {
        game.timeCount =  PERIOD_OPEN_END_4;
    }

    return seat.niuX;
};

function suanJinhua(holds) {
    //豹子10
    //同花顺 9
    //同花 8
    //顺子 7
    //对子 6
    //单牌 5
    //235  4
    var paiType = 0;

    //临时pai数组
    var paisArr = new Array(5);
    //临时paiMap
    var paisMap = new Map();
    for (var k = 0; k < 3; k++) {
        var pai = holds[k];
        //14--25,26
        pai = pai%13;
        if (pai === 0) {
            pai = 13;
        }
        paisMap.set(pai, 1);
        paisArr.push(pai);
    }
    paisArr = paisArr.sort(function (a, b) {
        return a - b; //从小到大
    });

    if (paisMap.size == 1) { //是否是豹子
        paiType = 10;
    } else if (paisMap.size == 2) { //是否是对子
        paiType = 6;
    } else {
        var isShunzi = beShunzi(paisArr);
        var isTonghua = beTonghua(holds);
        if (isShunzi && isTonghua) {
            paiType = 9;
        } else if (isTonghua) {
            paiType = 8;
        } else if (isShunzi) {
            paiType = 7;
        } else if (be235(paisArr)) {
            paiType = 4;
        } else {
            paiType = 5;
        }
    }
    return paiType;
}

function beTonghua(holds) {
    var isTonghua = false;
    //是否是同花
    var type = getPKType(holds[0]);
    for (var i = 1; i < 3; i++) {
        if (getPKType(holds[i]) == type) { //同一种花色
            isTonghua = true;
        } else {
            isTonghua = false;
            break;
        }
    }
    return isTonghua;
};

function beShunzi(holds) {
    //是否是顺子 AKQ
    var isShunzi = false;
    //是否是同花
    var pai = holds[0];
    for (var i = 1; i < 3; i++) {
        var temp = holds[i];
        if (temp == 1) {
            temp += 13;
        }
        if (Math.abs(pai - temp) == 1) { //相差等于1 有成为顺子的机会
            pai = temp;
            isShunzi = true;
        } else {
            isShunzi = false;
            break;
        }
    }
    return isShunzi;
};

function be235(holds) {
    var is235 = false;
    for (var i = 0; i < 3; i++) {
        if (i == 0 && holds[i] == 2) {
            is235 = true;
        } else if (i == 1 && holds[i] == 3) {
            is235 = true;
        } else if (i == 2 && holds[i] == 5) {
            is235 = true;
        } else {
            is235 = false;
            break;
        }
    }
    return is235;
};

function randomIndex(num) { //0到x取值
    return Math.floor(Math.random() * num);
}

exports.begin = begin;
exports.end = end;
exports.qiangZhuang = qiangZhuang;
exports.xiaZhu = xiaZhu;
exports.kaiPai = kaiPai;

exports.gameState = function (roomId) {
    var game = games[roomId];
    if (game == null) return;

    return game.state;
};



















